/**
 * @file ftpgetfiles1.cpp
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2024-05-09
 *
 * @copyright Copyright (c) 2024
 *
 */
#include <iostream>
#include "../../public/_ftp.h"
#include "../../public/_public.h"

void help(); // help文档
// 参数解析，放到一个结构体中
struct st_arg
{
    char host[31];          // 远程服务器的IP和端口。
    int mode;               // 传输模式，1-被动模式，2-主动模式，缺省采用被动模式。
    char username[31];      // 远程服务器ftp的用户名。
    char password[31];      // 远程服务器ftp的密码。
    char remotepath[301];   // 远程服务器存放文件的目录。
    char localpath[301];    // 本地文件存放的目录。
    char matchname[101];    // 待下载文件匹配的规则。
    char listfilename[301]; // 存放文件名 的文件的名字

} starg;

// 文件信息结构体
struct st_fileinfo
{
    char filename[301]; // 文件名。不存储路径信息
    char mtime[21];     // 文件时间。
};

CLogFile logfile; // 日志
Cftp ftp;
CFile file;
vector<st_fileinfo> vlistfile;
struct st_fileinfo stfileinfo;

void _xmltoarg(char *strxmlbuffer);
bool _ftpgetfiles();
bool LoadListFile();

int main(int argc, char *argv[]) // argv[2]
{
    if (argc != 3)
    {
        help();
        return -1;
    }
    // 打开日志
    if (false == logfile.Open(argv[1]))
    {
        printf("打开日志失败\n");
        return -1;
    }
    _xmltoarg(argv[2]);

    // 处理缺省参数缺省参数
    if (starg.mode != 2)
    {
        starg.mode = 1;
    }
    if (_ftpgetfiles() == false)
    {
        return -1;
    }

    return 0;
}
void help()
{
    printf("\n");
    printf("Using:/project/tools1/bin/ftpgetfiles logfilename xmlbuffer\n\n");

    printf("Sample:/project/tools1/bin/procctl 30 /project/tools1/bin/ftpgetfiles /log/idc/ftpgetfiles_surfdata.log \"<host>127.0.0.1:21</host><mode>1</mode><username>wucz</username><password>wuczpwd</password><localpath>/idcdata/surfdata</localpath><remotepath>/tmp/idc/surfdata</remotepath><matchname>SURF_ZH*.XML,SURF_ZH*.CSV</matchname>\"\n\n\n");

    printf("本程序是通用的功能模块，用于把远程ftp服务器的文件下载到本地目录。\n");
    printf("logfilename是本程序运行的日志文件。\n");
    printf("xmlbuffer为文件下载的参数，如下：\n");
    printf("<host>127.0.0.1:21</host> 远程服务器的IP和端口。\n");
    printf("<mode>1</mode> 传输模式，1-被动模式，2-主动模式，缺省采用被动模式。\n");
    printf("<username>wucz</username> 远程服务器ftp的用户名。\n");
    printf("<password>wuczpwd</password> 远程服务器ftp的密码。\n");
    printf("<remotepath>/tmp/idc/surfdata</remotepath> 远程服务器存放文件的目录。\n");
    printf("<localpath>/idcdata/surfdata</localpath> 本地文件存放的目录。\n");
    printf("<matchname>SURF_ZH*.XML,SURF_ZH*.CSV</matchname> 待下载文件匹配的规则。"
           "不匹配的文件不会被下载，本字段尽可能设置精确，不建议用*匹配全部的文件。\n\n\n");
    printf("<listfilename>/idcdata/ftplist/ftpgetfiles_surfdata.list</listfilename> 下载前列出服务器文件名的文件。\n\n\n");
}
//"./ftpgetfiles /wanyingxing/project/log/ftpget.log
//<host>192.168.9.242</host><mode>1</mode><username>root</username><password>Wanyingxing0</password><remotepath>/wanyingxing/project/surfdata</remotepath><localpath>/wanyingxing/project/idcdata/surfdata</localpath><matchname>SURF_ZH*.XML,SURF_ZH*.CSV</matchname><listfilename>/wanyingxing/project/idcdata/ftplist/ftpgetfiles_surfdata.list</listfilename>"

void _xmltoarg(char *strxmlbuffer)
{

    // xml
    // bool GetXMLBuffer(const char *xmlbuffer,const char *fieldname,char *value,const int ilen=0);
    memset(&starg, 0, sizeof(st_arg));
    if (false == GetXMLBuffer(strxmlbuffer, "host", starg.host))
    {
        printf("解析host失败\n");
        logfile.Write("解析host失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "mode", &starg.mode))
    {
        printf("解析mode失败\n");
        logfile.Write("解析mode失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "username", starg.username))
    {
        printf("解析username失败\n");
        logfile.Write("解析username失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "password", starg.password))
    {
        printf("解析password失败\n");
        logfile.Write("解析password失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "remotepath", starg.remotepath))
    {
        printf("解析remotepath失败\n");
        logfile.Write("解析remotepath失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "localpath", starg.localpath))
    {
        printf("解析localpath失败\n");
        logfile.Write("解析localpath失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "matchname", starg.matchname))
    {
        printf("解析matchname失败\n");
        logfile.Write("解析matchname失败\n");
    }
    if (false == GetXMLBuffer(strxmlbuffer, "listfilename", starg.listfilename))
    {
        printf("解析listfilename失败\n");
        logfile.Write("解析listfilename失败\n");
    }
    printf("解析参数成功\n");
}
bool _ftpgetfiles()
{
    // 连接服务器   bool login(const char *host,const char *username,const char *password,const int imode=FTPLIB_PASSIVE);
    if (false == ftp.login(starg.host, starg.username, starg.password, starg.mode))
    {
        logfile.Write("登陆失败\n");
        printf("登陆失败\n");
        return false;
    }
    // 进入服务器目录
    if (ftp.chdir(starg.remotepath) == false)
    {
        logfile.Write("进入目录失败\n");
        printf("进入目录失败\n");
        return false;
    }
    // 读取目录下的文件，存放到一个本地文件中   bool nlist(const char *remotedir,const char *listfilename);
    if (false == ftp.nlist(".", starg.listfilename))
    {
        logfile.Write("访问文件夹失败\n");
        printf("访问文件夹失败\n");
        return false;
    }

    if (LoadListFile() == false)
    {
        logfile.Write("加载文件失败\n");
        printf("加载文件失败\n");
        return false;
    }

    // 循环下载文件，也可以先写一个函数,凭借字符串全路径
    // 遍历容器vlistfile。
    char strremotefilename[301], strlocalfilename[301];
    for (int ii = 0; ii < vlistfile.size(); ii++)
    {
        // 拼接成为全路径，vectpor中存放的不是全路径的文件名，仅仅是文件名
        SNPRINTF(strremotefilename, sizeof(strremotefilename), 300, "%s/%s", starg.remotepath, vlistfile[ii].filename);
        SNPRINTF(strlocalfilename, sizeof(strlocalfilename), 300, "%s/%s", starg.localpath, vlistfile[ii].filename);

        // 调用ftp.get()方法从服务器下载文件。
        logfile.Write("get %s ...", strremotefilename);

        if (ftp.get(strremotefilename, strlocalfilename) == false)
        {
            logfile.WriteEx("failed.\n");
            break;
        }

        logfile.WriteEx("ok.\n");
    }

    return true;
}

// 读取文件时，不仅仅读取了文件的名
// 文件修改时间
// 只读取了文件名
// 为了完善，要一个结构体，及存储文件，也要存储文件时间，vector存储哪些文件信息即可

bool LoadListFile()
{
    // 过滤并且村发给到容器,打开一个文件，都这个文件，检查是否符合匹配规则，存放到容器中
    file.Open(starg.listfilename, "r");

    // 初始化
    memset(&stfileinfo, 0, sizeof(st_fileinfo));
    while (true)
    {
        // 循环读文件一行
        if (false == file.Fgets(stfileinfo.filename, 300, true))
        {
            break;
        }
        if (MatchStr(stfileinfo.filename, starg.matchname) == false)
            continue; // 如果文件不符合匹配规则

        //
        vlistfile.push_back(stfileinfo); // 这里把文件信息存放计入，这里存放的就没有路径信息，否在待会逻辑说不通
        memset(&stfileinfo, 0, sizeof(st_fileinfo));
    }
    return true;
}
